/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package swatsoft3.controlador;

import java.util.*;
import java.io.*;
import gov.nih.nlm.nls.nlp.textfeatures.*;
import gov.nih.nlm.nls.nlp.lexicallookup.LexicalLookupAPI;
import gov.nih.nlm.nls.nlp.parser.Parse;
import gov.nih.nlm.nls.utils.GlobalBehavior;
import java.util.logging.Level;
import java.util.logging.Logger;
import swatsoft3.modelo.BE_Documento;
import swatsoft3.modelo.BE_Frase;
import swatsoft3.modelo.BE_Oracion;

/**
 *
 * @author renzo
 */
public class BL_GestorAlgoritmo {

    public static BE_Documento procesamientoSintactico(String nomArchivo) throws Exception {

        BE_Documento documentoResultado = null;

        //Settings para el API que hace el análisis sintáctico
        String[] nlpSettings = new String[2];
        nlpSettings[0] = "--inputType=freeText";
        nlpSettings[1] = "--useTagger";
        GlobalBehavior settings = new GlobalBehavior("Parser", "NLPRegistry.cfg", "", nlpSettings);
        //crear el cliente que hace el análisis sintáctico       
        Parse parser = new Parse(settings);

        //Aquí se lee el archivo
        File aFile = new File(nomArchivo);

        //se conecta al cliente sintáctico y se procesa
        Document aDoc = null;
        aDoc = parser.processDocument(aFile);

        //armar nuestro propia estructura de documento a partir de la de SPECIALIST para manejarlo más fácil
        BE_Documento unDocumento = new BE_Documento();
        unDocumento.setRuta(nomArchivo);

        //se obtiene las oraciones y se tranforma a nuestro tipo de oración
        Vector sentences = aDoc.getSentences();
        int numberOfSentences = sentences.size();
        //Se define algunas variables para usar luego
        Sentence aSentence = null;
        Phrase aPhrase = null;
        Vector terms = null;

        //recorrer cada oración
        for (int i = 0; i < numberOfSentences; i++) {

            //obtener las frases de la oración
            aSentence = (Sentence) sentences.get(i);
            Vector phrases = aSentence.getPhrases();
            int numberOfPhrases = phrases.size();
            BE_Oracion unaOracion = new BE_Oracion();
            unaOracion.setOracion(aSentence.getOriginalString());

            for (int j = 0; j < numberOfPhrases; j++) {
                aPhrase = (Phrase) phrases.get(j);
                BE_Frase unaFrase = new BE_Frase();

                //Asignar la cadena original de la frase
                unaFrase.setCadenaFrase(aPhrase.getOriginalString());

                //Asignar el tipo sintáctico
                unaFrase.setTipoSintactico(aPhrase.getTypeOfPhraseString());
                if (aPhrase.isNounPhrase()) unaFrase.setTipoSintactico(BL_GestorMetamap.fraseNominal);
                if (aPhrase.isPrepPhrase()) unaFrase.setTipoSintactico(BL_GestorMetamap.frasePreposicional);
                //Asignar el elemento cabeza o elemento léxico núcleo, para luego hacer correferencia por hiperónimo/hipónimo
                Vector listaElementos = aPhrase.getLexicalElements();
                //Hay que recorrer todos los elementos hasta ubicar la cabeza, se guarda en mayúscula para evitar problemas
                for (Object elemento : listaElementos) {
                    LexicalElement elementoLexico = (LexicalElement) elemento;
                    if (elementoLexico.isHead()) {
                        unaFrase.setElementoLexicoCabeza(elementoLexico.getOriginalString().toUpperCase());
                    }
                }

                //añadir BE_Frase a mi propia oración
                unaOracion.addFrase(unaFrase);

                System.out.println("Frase: "+aPhrase.getOriginalString());
                System.out.println("Tipo sintáctico: "+aPhrase.getTypeOfPhraseString());
                System.out.println("Elementos léxicos");
            }

            //añadir BE_Oracion a mi propio documento
            unDocumento.addOracion(unaOracion);

        }
        documentoResultado = unDocumento;
        return documentoResultado;
        //fin de método
    }

    public static void procesamientoSemantico(BE_Documento documento) throws Exception {

        for (BE_Oracion oracion : documento.getListaOraciones()) {
            ArrayList<BE_Frase> listaFrases = oracion.getListaFrases();
            for (BE_Frase frase : listaFrases) {
                //Verifica que sea frase nominal o preposicional
                if ((frase.getTipoSintactico().compareToIgnoreCase(BL_GestorMetamap.fraseNominal) == 0) || (frase.getTipoSintactico().compareToIgnoreCase(BL_GestorMetamap.frasePreposicional) == 0)) {
                    BL_GestorMetamap.asignarConceptoUnicoYTipoSemantico(frase);
                }
            }
        }
    }

    public static ArrayList<BE_Oracion> analizaCorreferencia(BE_Documento documento, String conceptoUnico) throws Exception {
        ArrayList<BE_Oracion> listaCorreferencia = new ArrayList<BE_Oracion>();

        for (BE_Oracion oracion : documento.getListaOraciones()) {
            //correferencia por concepto único e hiperónimo/hipónimo
            //Analizar todas las frases de la oración y si una coincide, hay correferencia
            boolean esCorreferentePorCU = false;
            boolean esCorreferentePorHH = false;

            for (BE_Frase frase : oracion.getListaFrases()) {
                if (frase.getConceptoUnico().equalsIgnoreCase(conceptoUnico)) {
                    esCorreferentePorCU = true;
                    break;
                }

                if (coincideHiperHiponimo(frase, conceptoUnico)) {
                    esCorreferentePorHH = true;
                    break;
                }

            }

            if (esCorreferentePorCU || esCorreferentePorHH) {
                listaCorreferencia.add(oracion);
            }

        }
        return listaCorreferencia;
    }

    public static boolean coincideHiperHiponimo(BE_Frase frase, String conceptoUnico) throws Exception {
        Boolean resultado = false;

        String conceptoUNICO = conceptoUnico.toUpperCase();
        
        //Se ve si la cabeza de la frase está incluída en el concepto único, y que su tipo semántico sea enfermedad
        if (conceptoUNICO.contains(frase.getElementoLexicoCabeza()) && (frase.getTipoSemantico() == BL_GestorMetamap.enfermedad)) {
            resultado = true;
        }

        return resultado;
    }

    public static ArrayList<ArrayList<String>> imprimeSintomasYCuras(ArrayList<BE_Oracion> listaCorreferencia, String archivo) throws Exception {
        ArrayList<ArrayList<String>> resultado = new ArrayList<ArrayList<String>>();
        boolean hay = false;

        for (BE_Oracion oracion : listaCorreferencia) {
            for (BE_Frase frase : oracion.getListaFrases()) {
                ArrayList<String> aux = new ArrayList<String>();
                if ((frase.getTipoSemantico().equals(BL_GestorMetamap.sintoma)) || frase.getTipoSemantico().equals(BL_GestorMetamap.cura)) {
                    hay = true;
                    aux.add(archivo);
                    aux.add(oracion.getOracion());
                    if (frase.getTipoSemantico().equals(BL_GestorMetamap.sintoma)) {
                        aux.add("Síntoma");
                    } else {
                        aux.add("Cura");
                    }

                    aux.add(frase.getConceptoUnico());
                } else {
                    hay = false;
                }

                if (hay) {
                    resultado.add(aux);
                }
                hay = false;
            }
        }
        return resultado;
    }
}
